tipos software pattern patrones lista ejemplos diseño diseno arquitectura design-patterns validation oop

design patterns - software - Patrones de diseño de validación de datos



patrones de diseño lista (5)

Creo que en realidad estás hablando de un concepto llamado restricciones en el mundo de las bases de datos. Las restricciones son cómo una base de datos garantiza la integridad de los datos que contiene. Tiene mucho más sentido colocar este tipo de lógica en la base de datos, en lugar de la aplicación (incluso Access ofrece formas rudimentarias de restricciones, como requerir valores únicos en una columna, o valores de una lista, etc.).
La validación de entrada (de campos individuales) es, por supuesto, una cuestión diferente, y cualquier aplicación debería seguir haciéndolo (para proporcionar comentarios agradables al usuario en caso de problemas), incluso si la BD tiene restricciones bien definidas de las columnas de la tabla.

Si tengo una colección de tablas de base de datos (en un archivo de Access, por ejemplo) y necesito validar cada tabla en esta colección en comparación con un conjunto de reglas que tiene reglas comunes en todas las tablas, así como reglas individuales específicas para uno o un subconjunto de tablas, ¿alguien puede recomendar un buen patrón de diseño para estudiar?

Específicamente, me gustaría evitar un código similar a:

void Main() { ValidateTable1(); ValidateTable2(); ValidateTable3(); } private void ValidateTable1() { //Table1 validation code goes here } private void ValidateTable2() { //Table2 validation code goes here } private void ValidateTable3() { //Table3 validation code goes here }

Además, he decidido usar log4net para registrar todos los errores y advertencias, para que cada método pueda declararse void y no necesite devolver nada. ¿Es esta una buena idea o sería mejor crear algún tipo de ValidationException que capture todas las excepciones y las almacene en una List<ValidationException> antes de imprimirlas todas al final?

Encontré esto , que parece que puede funcionar, pero espero encontrar algunos ejemplos de código para trabajar. ¿Alguna sugerencia? ¿Alguien ha hecho algo similar en el pasado?

Para algunos antecedentes, el programa se escribirá en C # o VB.NET y es muy probable que las tablas se almacenen en Access o SQL Server CE.


Devolvería algún tipo de ValidationSummary para cada uno ... o un IList dependiendo de cómo quiera estructurarlo.

también puedes optar por hacer magia como esta:

using(var validation = new ValidationScope()) { ValidateTable1(); ValidateTable2(); ValidateTable3(); if(validation.Haserrors) { MessageBox.Show(validation.ValidationSummary); return; } DoSomethingElse(); }

entonces ValidateTable simplemente alcanzaría el alcance actual, así:

ValidationScope.Current.AddError("col1", "Col1 should not be NULL");

algo para ese efecto.


Solo una actualización sobre esto: decidí ir con el patrón Decorator . Es decir, tengo una clase de tabla ''genérica'' que implementa una interfaz IValidateableTable (que contiene un método Validate() . Luego creé varios decoradores de validación (que también implementan IValidateableTable) que puedo envolver alrededor de cada tabla que intento validar.

Entonces, el código termina luciendo así:

IValidateableTable table1 = new GenericTable(myDataSet); table1 = new NonNullNonEmptyColumnValidator(table1, "ColumnA"); table1 = new ColumnValueValidator(table1, "ColumnB", "ExpectedValue");

Entonces, todo lo que necesito hacer es llamar a table1.Validate() que se desenrolla a través de los decoradores llamando a todas las validaciones necesarias. Hasta ahora, parece estar funcionando realmente bien, aunque todavía estoy abierto a sugerencias.


Dos enfoques:

  1. CSLA donde se utilizan métodos anónimos en objetos comerciales para la validación.
  2. Lea el blog de JP Boodhoo donde ha implementado un motor de reglas y ha publicado publicaciones detalladas y ejemplos de código. También puedes verlo trabajando en el episodio de DNR Tv que vale la pena ver.

Lo intentaría con una combinación de los patrones Factory y Visitor:

using System; using System.Collections.Generic; namespace Example2 { interface IVisitor { void Visit(Table1 table1); void Visit(Table2 table2); } interface IVisitable { void Accept(IVisitor visitor); } interface ILog { void Verbose(string message); void Debug(string messsage); void Info(string message); void Error(string message); void Fatal(string message); } class Error { public string Message { get; set; } } class Table1 : IVisitable { public int Id { get; set; } public string Data { get; set; } private IList<Table2> InnerElements { get; } = new List<Table2>(); public void Accept(IVisitor visitor) { visitor.Visit(this); foreach(var innerElement in InnerElements) visitor.Visit(innerElement); } } class Table2 : IVisitable { public int Id { get; set; } public int Data { get; set; } public void Accept(IVisitor visitor) { visitor.Visit(this); } } class Validator : IVisitor { private readonly ILog log; private readonly IRuleSet<Table1> table1Rules; private readonly IRuleSet<Table2> table2Rules; public Validator(ILog log, IRuleSet<Table1> table1Rules, IRuleSet<Table2> table2Rules) { this.log = log; this.table1Rules = table1Rules; this.table2Rules = table2Rules; } public void Visit(Table1 table1) { IEnumerable<Error> errors = table1Rules.EnforceOn(table1); foreach (var error in errors) log.Error(error.Message); } public void Visit(Table2 table2) { IEnumerable<Error> errors = table2Rules.EnforceOn(table2); foreach (var error in errors) log.Error(error.Message); } } class RuleSets { private readonly IRuleSetFactory factory; public RuleSets(IRuleSetFactory factory) { this.factory = factory; } public IRuleSet<Table1> RulesForTable1 => factory.For<Table1>() .AddRule(o => string.IsNullOrEmpty(o.Data), "Data1 is null or empty") .AddRule(o => o.Data.Length < 10, "Data1 is too short") .AddRule(o => o.Data.Length > 26, "Data1 is too long"); public IRuleSet<Table2> RulesForTable2 => factory.For<Table2>() .AddRule(o => o.Data < 0, "Data2 is negative") .AddRule(o => o.Data > 10, "Data2 is too big"); } interface IRuleSetFactory { IRuleSet<T> For<T>(); } interface IRuleSet<T> { IEnumerable<Error> EnforceOn(T obj); IRuleSet<T> AddRule(Func<T, bool> rule, string description); } class Program { void Run() { var log = new ConsoleLogger(); var factory = new SimpleRules(); var rules = new RuleSets(factory); var validator = new Validator(log, rules.RulesForTable1, rules.RulesForTable2); var toValidate = new List<IVisitable>(); toValidate.Add(new Table1()); toValidate.Add(new Table2()); foreach (var validatable in toValidate) validatable.Accept(validator); } } }