Which pattern is used to validate business rule?

6

I use repository patterns for search, save, and delete

I would like to know where the validation of my business is best ...

For example:

I need to check that item is in contrato of prestador , and invoice it with the commission that is in the contract.

Is there a business rule there, where would it fit best to do this? In Dao classes? in the repository itself (I do not know if that can be done) Here where I work are passing this rule in the controller, which I do not think correct, I would like opinions

    
asked by anonymous 12.06.2014 / 14:51

2 answers

4

The @utluiz response is correct within a 3 layer context (presentation, service, and data), but as we are talking about MVC, validation should be done essentially in Model , but not only in it.

Why?

The essential function of Model is to model how information circulates within the system from the point of view of each entity. The essential function of Controller is to harmonize and coordinate the information flows - coming from the presentation, the data layer or some external service.

Therefore, validation functions for any given data are usually generated at Model level. The Controller only interprets this result of the validations. This is done because validation is an aspect at the data level. Elegantly, this is done in ASP.NET MVC using Attributes .

Meanwhile, relationships between entities ( Models ) are resolved at Controller level (comparisons, insertions, deletions, sorts, etc.).

Examples

Consider Model Pessoa below:

public class Pessoa 
{
    [Key]
    public Guid PessoaId {get;set;}

    [Display(Name = "Nome")]
    [Required(ErrorMessage = "O preenchimento do nome da pessoa é obrigatório.")]
    public String Nome {get;set;}

    [Required(ErrorMessage = "O preenchimento do CPF da pessoa é obrigatório.")]
    [CPF]
    public Decimal Cpf {get;set;}

    public virtual ICollection<Produto> Produtos {get;set;}
}

When saving a Pessoa to a database, I do not need to write a validation row in my Controller because all aspects of data are being treated within Model succinctly: the CPF has an attribute that validates the CPF, the name can not be filled empty and the primary key must be unique ( [Key] ).

The Controller does nothing here, but check through another class if the Model is valid:

[HttpPost]
public ActionResult Create(Pessoa pessoa)
{
    // Se o Model for válido
    if (ModelState.IsValid) 
    {
        // Gera a chave, salva e retorna
        pessoa.PessoaId = Guid.NewGuid();
        context.Pessoas.Add(pessoa);
        context.SaveChanges();
        return RedirectToAction("Index");
    }

    // Se não for válido, simplesmente retorna o objeto Pessoa de novo.
    // O resultado das validações está dentro da classe ModelState.

    return View(pessoa);
}

Now suppose I want to give a discount on a Produto purchased by the user. This is dealt with in Controller because we are dealing with a Pessoa and Produtos acquired by it:

public class PessoasController : Controller 
{
    ...

    public ActionResult ConcederDescontoUltimoProduto(Guid? id) 
    {
        var pessoa = context.Pessoas.Include(p => p.Produtos).SingleOrDefault(p => p.PessoaId == id);

        if (pessoa.Produtos.Count > 5) 
        {
            var produto = pessoa.Produtos.Last();
            // Vou conceder 10% de desconto no valor do produto
            produto.Preco -= produto.Preco * 0.1;
            context.Entry(produto).State = EntityState.Modified;
            context.SaveChanges();
        }

        return RedirectToAction("Index");
    }
}

It is also possible to leave this negotiating aspect in charge of other specific classes, but I consider a long and unnecessary effort, in which nothing contributes to the security and class responsibility of the system.

    
12.06.2014 / 21:27
4

The most commonly used standard (even without knowledge) is the Service Layer .

Service Layer Design Pattern

The architecture of an application is usually divided into layers that go from the database to the user interface or to external systems.

In the middle of it all are business rules. They are not part of the data model, although you use it. Also it would not be the responsibility of the controllers and much less of the views, although these need access to the business rules.

This is well represented in the following image:

Theserviceslayermustimplementthecorefunctionalityofthesystemandprovideallofthemtothe"outside world" through a well-defined interface.

This prevents the system core from being exposed directly to the "higher" layers of the architecture, otherwise the coupling would make maintenance a real nightmare.

References

12.06.2014 / 18:06